import * as THREE from 'three';
import { CONFIG } from '@/core/constants';
import { BlockType } from '@/blocks/types';
import { BlockMesh } from '@/blocks/BlockMesh';
import { getBlock } from '@/blocks/BlockRegistry';
import { Chunk } from './Chunk';

export class ChunkMeshBuilder {
  constructor() {
    BlockMesh.init();
  }

  public buildChunkMesh(chunk: Chunk): THREE.Group | null {
    const chunkGroup = new THREE.Group();
    const opaqueBlockPositions: Map<BlockType, THREE.Vector3[]> = new Map();
    const transparentBlockPositions: Map<BlockType, THREE.Vector3[]> = new Map();

    for (let x = 0; x < CONFIG.CHUNK_SIZE; x++) {
      for (let y = 0; y < CONFIG.WORLD_HEIGHT; y++) {
        for (let z = 0; z < CONFIG.CHUNK_SIZE; z++) {
          const blockType = chunk.getBlock(x, y, z);
          
          if (blockType === BlockType.AIR) continue;
          
          if (this.shouldRenderBlock(chunk, x, y, z)) {
            const worldX = chunk.position.x * CONFIG.CHUNK_SIZE + x;
            const worldY = y;
            const worldZ = chunk.position.z * CONFIG.CHUNK_SIZE + z;
            
            const position = new THREE.Vector3(worldX, worldY, worldZ);
            const block = getBlock(blockType);
            
            // 分离透明和不透明方块
            if (block.properties.transparent) {
              if (!transparentBlockPositions.has(blockType)) {
                transparentBlockPositions.set(blockType, []);
              }
              transparentBlockPositions.get(blockType)!.push(position);
            } else {
              if (!opaqueBlockPositions.has(blockType)) {
                opaqueBlockPositions.set(blockType, []);
              }
              opaqueBlockPositions.get(blockType)!.push(position);
            }
          }
        }
      }
    }

    // 先渲染不透明方块
    for (const [blockType, positions] of opaqueBlockPositions) {
      if (positions.length > 0) {
        const instancedMesh = BlockMesh.createInstancedBlockMesh(blockType, positions);
        if (instancedMesh) {
          chunkGroup.add(instancedMesh);
        } else {
          console.warn(`Failed to create instanced mesh for block type ${blockType}`);
        }
      }
    }

    // 然后渲染透明方块
    for (const [blockType, positions] of transparentBlockPositions) {
      if (positions.length > 0) {
        const instancedMesh = BlockMesh.createTransparentInstancedBlockMesh(blockType, positions);
        if (instancedMesh) {
          chunkGroup.add(instancedMesh);
        } else {
          console.warn(`Failed to create transparent instanced mesh for block type ${blockType}`);
        }
      }
    }

    return chunkGroup.children.length > 0 ? chunkGroup : null;
  }

  private shouldRenderBlock(chunk: Chunk, x: number, y: number, z: number): boolean {
    const blockType = chunk.getBlock(x, y, z);
    const block = getBlock(blockType);
    
    if (!block.solid) return true;
    
    const neighbors = [
      chunk.getBlock(x + 1, y, z),
      chunk.getBlock(x - 1, y, z),
      chunk.getBlock(x, y + 1, z),
      chunk.getBlock(x, y - 1, z),
      chunk.getBlock(x, y, z + 1),
      chunk.getBlock(x, y, z - 1)
    ];
    
    return neighbors.some(neighborType => {
      if (neighborType === BlockType.AIR) return true;
      const neighborBlock = getBlock(neighborType);
      return neighborBlock.properties.transparent;
    });
  }
}